"""
RabbitMQ 死信队列处理模块
"""

import asyncio
import aio_pika
import json
import logging
from datetime import datetime
from typing import Dict, Any

from .config import config

logger = logging.getLogger(__name__)


class DeadLetterConsumer:
    """死信队列消费者"""
    
    def __init__(self):
        """初始化死信队列消费者"""
        self.connection = None
        self.channel = None
        self.dead_letter_queue = None
        
    async def connect(self):
        """建立连接"""
        try:
            connection_config = config.get_connection_config()
            self.connection = await aio_pika.connect_robust(connection_config['uri'])
            self.channel = await self.connection.channel()
            await self.channel.set_qos(prefetch_count=connection_config['prefetch_count'])
            
            # 声明死信队列
            dead_letter_config = config.get_dead_letter_config()
            self.dead_letter_queue = await self.channel.declare_queue(
                dead_letter_config['dead_letter_queue'],
                durable=True,
                auto_delete=False
            )
            
            logger.info("[死信消费者] 已连接")
            
        except Exception as e:
            logger.error(f"[死信消费者] 连接失败: {e}")
            raise
    
    async def process_dead_letter_message(self, message: aio_pika.IncomingMessage):
        """处理死信消息"""
        try:
            # 解析死信消息
            dead_letter_data = json.loads(message.body.decode('utf-8'))
            original_message = dead_letter_data.get('original_message', {})
            error_info = dead_letter_data.get('error_info', 'Unknown')
            message_id = dead_letter_data.get('message_id', 'Unknown')
            
            # 打印死信消息信息
            logger.error("=" * 50)
            logger.error("[死信消费者] 收到死信消息:")
            logger.error(f"[死信消费者] 消息ID: {message_id}")
            logger.error(f"[死信消费者] 消息内容: {json.dumps(original_message, ensure_ascii=False, indent=2)}")
            logger.error(f"[死信消费者] 错误原因: {error_info}")
            logger.error("=" * 50)
            
            # 保存到数据库
            await self.save_to_database(original_message, error_info, message_id)
            
            # 确认死信消息
            await message.ack()
            logger.info(f"[死信消费者] 死信消息 {message_id} 处理完成")
            
        except Exception as e:
            logger.error(f"[死信消费者] 处理死信消息失败: {e}")
            await message.nack(requeue=False) # 拒绝重新入队，避免一致失败出现的死循环
    
    async def save_to_database(self, original_message: Dict[str, Any], error_info: str, message_id: str):
        """保存死信消息到数据库"""
        # 模拟数据库保存操作
        await asyncio.sleep(0.5)
        
        # 构建数据库记录
        db_record = {
            'id': message_id,
            'original_message': original_message,
            'error_info': error_info,
            'created_at': datetime.now().isoformat(),
            'status': 'failed'
        }
        
        logger.info(f"[死信消费者] 💾 死信消息已保存到数据库: {message_id}")
        logger.info(f"[死信消费者] 数据库记录: {json.dumps(db_record, ensure_ascii=False, indent=2)}")
        
        # 这里可以添加实际的数据库操作
        # 例如：await database.insert('dead_letter_messages', db_record)
    
    async def start_consuming(self):
        """开始消费死信消息"""
        self.consumer_tag = await self.dead_letter_queue.consume(self.process_dead_letter_message)
        logger.info("[死信消费者] 开始消费死信消息...")
        
        # 保持消费者运行
        await asyncio.Future()
    
    async def stop_consuming(self):
        """停止消费死信消息"""
        if self.dead_letter_queue and self.consumer_tag:
            await self.dead_letter_queue.cancel(self.consumer_tag)
            logger.info("[死信消费者] 已停止消费死信消息")
    
    async def close(self):
        """关闭连接"""
        try:
            await self.stop_consuming()
            if self.connection:
                await self.connection.close()
                logger.info("[死信消费者] 连接已关闭")
        except Exception as e:
            logger.error(f"[死信消费者] 关闭连接时出错: {e}")
    
    async def __aenter__(self):
        """异步上下文管理器入口"""
        await self.connect()
        return self
    
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        """异步上下文管理器出口"""
        await self.close()

